﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

namespace SOEN341_SCHEDULER_PHASE1
{
    /// <summary>
    /// Custom datetime made for the classes start/end time and day of the week
    /// </summary>
    [Serializable()]
    class CustomDateTime:ISerializable
    {
        #region Constant Variables

        const int MIN_VALUE_HOUR = 7;
        const int MAX_VALUE_HOUR = 22;
        const int MIN_VALUE_MINUTE = 0;
        const int MAX_VALUE_MINUTE = 60;
        #endregion

        #region Member Variables
        int _startHour;
        int _startMinute;
        int _endHour;
        int _endMinute;
        List<DayOfWeek> _dayOfTheWeek;
        #endregion

        #region Constructors

        /// <summary>
        /// Serialization constructor
        /// </summary>
        /// <param name="info"></param>
        /// <param name="ctxt"></param>
        public CustomDateTime(SerializationInfo info, StreamingContext ctxt)
        {
            _startHour = (int)info.GetValue("startH", typeof(int));
            _startMinute = (int)info.GetValue("startM", typeof(int));
            _endHour = (int)info.GetValue("endH", typeof(int));
            _endMinute = (int)info.GetValue("endM", typeof(int));
            _dayOfTheWeek = (List<DayOfWeek>)info.GetValue("dayW", typeof(List<DayOfWeek>));
        }

        /// <summary>
        /// Serialization method
        /// </summary>
        /// <param name="info"></param>
        /// <param name="ctxt"></param>
        public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
        {
            info.AddValue("startH", _startHour);
            info.AddValue("startM", _startMinute);
            info.AddValue("endH", _endHour);
            info.AddValue("endM", _endMinute);
            info.AddValue("dayW", _dayOfTheWeek);
        }

        /// <summary>
        /// default constructor
        /// </summary>
        public CustomDateTime()
        {
            _startHour = 0;
            _startMinute = 0;
            _endHour = 0;
            _endMinute = 0;
            _dayOfTheWeek = new List<DayOfWeek>();
        }

        /// <summary>
        /// Creates new CustomDateTime object with parameterized settings
        /// </summary>
        /// <param name="startHour">start hour time (0-22) *24 HOUR FORMAT*</param>
        /// <param name="startMinute">start minute time (0-60)</param>
        /// <param name="endHour">end hour time (0-22) *24 HOUR FORMAT*</param>
        /// <param name="endMinute">end minute time (0-60)</param>
        /// <param name="dayOfTheWeek">day of the week </param>
        public CustomDateTime(int startHour, int startMinute, int endHour, int endMinute, List<DayOfWeek> dayOfTheWeek)
        {
            //validate all 
            //validate all 
            if (startHour < MIN_VALUE_HOUR || startHour > MAX_VALUE_HOUR)
            {
                startHour = MIN_VALUE_HOUR;
            }
            if (startMinute < MIN_VALUE_MINUTE || startMinute > MAX_VALUE_MINUTE)
            {
                startMinute = MAX_VALUE_MINUTE;
            }
            if (endHour < MIN_VALUE_HOUR || endHour > MAX_VALUE_HOUR)
            {
                endHour = MIN_VALUE_HOUR;
            }
            if (endMinute < MIN_VALUE_MINUTE || endMinute > MAX_VALUE_MINUTE)
            {
                endMinute = MIN_VALUE_MINUTE;
            }

            _startHour = startHour;
            _startMinute = startMinute;
            _endHour = endHour;
            _endMinute = endMinute;

            _dayOfTheWeek=new List<DayOfWeek>();
            if (dayOfTheWeek != null)
            {
                DayOfWeek[] arrDay=dayOfTheWeek.ToArray();
                for (int i=0;i<arrDay.Length;i++)
                {
                    _dayOfTheWeek.Add(arrDay[i]);
                }
            }
        }

        /// <summary>
        /// Clone constructor
        /// </summary>
        /// <param name="cdt">Object to copy</param>
        public CustomDateTime(CustomDateTime cdt)
        {
            if (cdt != null)
            {
                _startHour = cdt.GetStartHour();
                _startMinute = cdt.GetStartMinute();
                _endHour = cdt.GetEndHour();
                _endMinute = cdt.GetEndMinute();
                List<DayOfWeek> dayOfTheWeek = cdt.GetDayOfWeek();

                _dayOfTheWeek = new List<DayOfWeek>();
                if (dayOfTheWeek != null)
                {
                    DayOfWeek[] arrDay = dayOfTheWeek.ToArray();
                    for (int i = 0; i < arrDay.Length; i++)
                    {
                        _dayOfTheWeek.Add(arrDay[i]);
                    }
                }
            }
            else
            {
                new CustomDateTime();
            }
        }

        #endregion

        #region Accessors

        /// <summary>
        /// get start hour
        /// </summary>
        /// <returns>start hour</returns>
        public int GetStartHour()
        {
            return _startHour;
        }

        /// <summary>
        /// get start minute
        /// </summary>
        /// <returns>start minute</returns>
        public int GetStartMinute()
        {
            return _startMinute;
        }

        /// <summary>
        /// get end hour
        /// </summary>
        /// <returns>end hour</returns>
        public int GetEndHour()
        {
            return _endHour;
        }

        /// <summary>
        /// get end minute
        /// </summary>
        /// <returns>end minute</returns>
        public int GetEndMinute()
        {
            return _endMinute;
        }

        /// <summary>
        /// get day of week (ENUM)
        /// </summary>
        /// <returns>day of week</returns>
        public List<DayOfWeek> GetDayOfWeek()
        {
            return _dayOfTheWeek;
        }

        /// <summary>
        /// to string method
        /// </summary>
        /// <returns>return object info</returns>
        public override string ToString()
        {
            //returns like that DAY_OF_WEEK || START_HOUR:START_MINUTE - END_HOUR:END_MINUTE
            string toret;

            toret = _dayOfTheWeek.ToString() + " || ";

            toret += _startHour.ToString() + ":";

            if (_startMinute < 10)
            {
                toret += "0" + _startMinute.ToString();
            }
            else
            {
                toret += _startMinute.ToString();
            }

            toret += " - ";
            
            toret += _endHour.ToString() + ":";

            if (_endMinute < 10)
            {
                toret += "0" + _endMinute.ToString();
            }
            else
            {
                toret += _endMinute.ToString();
            }

            return toret;


        }

        /// <summary>
        /// time interval in string format
        /// </summary>
        /// <returns>time interval</returns>
        public string GetTimeInterval()
        {
            string toret;

            toret = _startHour.ToString() + ":";

            if (_startMinute < 10)
            {
                toret += "0" + _startMinute.ToString();
            }
            else
            {
                toret += _startMinute.ToString();
            }

            toret += " - ";

            toret += _endHour.ToString() + ":";

            if (_endMinute < 10)
            {
                toret += "0" + _endMinute.ToString();
            }
            else
            {
                toret += _endMinute.ToString();
            }

            DayOfWeek[] arrDay = _dayOfTheWeek.ToArray();
            toret += " (";
            for (int i = 0; i < arrDay.Length; i++)
            {
                toret += arrDay[i].ToString()[0];
                if (i != arrDay.Length - 1)
                {
                    toret += "-";
                }
            }
            toret += ")";
            

            return toret;
        }

        #endregion

        /// <summary>
        /// Sets DayOfWeek
        /// </summary>
        /// <param name="theDay"></param>
        public void SetDayOfWeek(DayOfWeek theDay)
        {
            _dayOfTheWeek = new List<DayOfWeek>();
            _dayOfTheWeek.Add(theDay);
        }

        /// <summary>
        /// Equal method
        /// </summary>
        /// <param name="obj">Object to compare to</param>
        /// <returns>TRUE: Objects are equal - FALSE: Objects are not equal</returns>
        public override bool Equals(object obj)
        {
            CustomDateTime toComp = (CustomDateTime)obj;
            //get array of days
            DayOfWeek[] thisDayWeek = _dayOfTheWeek.ToArray();
            DayOfWeek[] compDayWeek = toComp.GetDayOfWeek().ToArray();
            if (thisDayWeek.Length != compDayWeek.Length)
                return false;
            for (int i = 0; i < thisDayWeek.Length; i++)
            {
                if (!thisDayWeek[i].Equals(compDayWeek[i]))
                    return false;
            }
            return (_startHour == toComp.GetStartHour() &&
                _startMinute == toComp.GetStartMinute() &&
                _endHour == toComp.GetEndHour() &&
                _endMinute == toComp.GetEndMinute());
        }
    }
}
